﻿using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace LevelEditor
{
    public class HeightMap
    {
        /// <summary>
        /// The height data for the map
        /// </summary>
        public RenderTarget2D data;

        /// <summary>
        /// Same as height data, but can be used in a vertex shader
        /// </summary>
        public RenderTarget2D vertexData;

        /// <summary>
        /// The normal data for the heightmap
        /// </summary>
        public RenderTarget2D normalMap;

        /// <summary>
        /// Render target used for debuggin' normal maps all visual and shit
        /// </summary>
        public RenderTarget2D normalMapDebug;

        /// <summary>
        /// The width, in pixels of the map
        /// </summary>
        public int MapWidth
        {
            get { return data.Width / 20; }
        }
        /// <summary>
        /// The height, in pixels of the map
        /// </summary>
        public int MapHeight
        {
            get { return data.Height / 20; }
        }

        /// <summary>
        /// The heighest possible point on the map
        /// </summary>
        public float heighest;
        /// <summary>
        /// The lowest possible point on the map
        /// </summary>
        public float lowest;
        
        /// <summary>
        /// Creates a new instance of heightmap
        /// </summary>
        /// <param name="width">the width of the map, in pixels</param>
        /// <param name="height">the height of the map, in pixels</param>
        /// <param name="lowest">a value that represents the lowest point on the map</param>
        /// <param name="heighest">a value that represents the heights possible point on the map</param>
        public HeightMap(int width, int height, float lowest, float heighest, GraphicsDevice device)
        {
            this.lowest = lowest;
            this.heighest = heighest;

            data = new RenderTarget2D(device,           width * 20, height * 20, false, SurfaceFormat.Color, DepthFormat.Depth24, 0, RenderTargetUsage.PreserveContents);
            vertexData = new RenderTarget2D(device,     width * 20, height * 20, false, SurfaceFormat.Vector4, DepthFormat.Depth24, 0, RenderTargetUsage.DiscardContents);
            normalMap = new RenderTarget2D(device,      width * 20, height * 20, false, SurfaceFormat.Vector4, DepthFormat.Depth24, 0, RenderTargetUsage.DiscardContents);
            normalMapDebug = new RenderTarget2D(device, width * 20, height * 20, false, SurfaceFormat.Color, DepthFormat.Depth24, 0, RenderTargetUsage.DiscardContents);
        }

        static ScreenQuad scr_quad = new ScreenQuad();

        /// <summary>
        /// Updates the vertex shader texture data
        /// </summary>
        public void Update()
        {
            data.GraphicsDevice.BlendState = BlendState.Opaque;
            data.GraphicsDevice.SetRenderTarget(vertexData);
            data.GraphicsDevice.Textures[0] = data;
            EffectManager.BasicShader.CurrentTechnique.Passes[0].Apply();
            data.GraphicsDevice.SamplerStates[0] = SamplerState.PointWrap;
            scr_quad.Draw();

            data.GraphicsDevice.SetRenderTarget(normalMap);
            Effect normalShader = EffectManager.heightMapShader;
            data.GraphicsDevice.Textures[0] = data;
            normalShader.Parameters["textureSize"].SetValue(new Vector2(normalMap.Width / 2.0f, normalMap.Height / 2.0f));
            normalShader.Parameters["range"].SetValue(heighest - lowest);
            normalShader.CurrentTechnique = EffectManager.heightMapShader.Techniques["renderNormals"];
            normalShader.CurrentTechnique.Passes[0].Apply();
            scr_quad.Draw();

            data.GraphicsDevice.SetRenderTarget(normalMapDebug);
            data.GraphicsDevice.Textures[0] = normalMap;
            EffectManager.BasicShader.CurrentTechnique.Passes[0].Apply();
            scr_quad.Draw();

            data.GraphicsDevice.SetRenderTarget(null);
        }
    }
}